*&---------------------------------------------------------------------*
*& Report  ZZCONNECT4
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*


*----------------------------------------------------------------------*
* CONNECT4 Game Program                                                *
* By Silva Huertas, modified by Neil Overton
*----------------------------------------------------------------------*
REPORT zzconnect4 NO STANDARD PAGE HEADING
                 MESSAGE-ID bd
                 LINE-SIZE  80
                 LINE-COUNT 65.

* Includes
INCLUDE <icon>.

* Global Variables
DATA: c1(8) TYPE c,
      c2(8) TYPE c,
      c3(8) TYPE c,
      c4(8) TYPE c,
      c5(8) TYPE c,
      c6(8) TYPE c,
      c7(8) TYPE c,
      c8(8) TYPE c.

* Temp Data
DATA: BEGIN OF temp,
        tmp_cini    TYPE i,
        tmp_cfin    TYPE i,
        tmp_lini    TYPE i,
        tmp_lfin    TYPE i,
        tmp_ca1(80) TYPE c,
        tmp_ca2(80) TYPE c,
        tmp_ca3(80) TYPE c,
        tmp_col1    TYPE i,
        tmp_col2    TYPE i,
        tmp_col3(2) TYPE c,
        tmp_col4(2) TYPE c,
        tmp_c1(2)   TYPE c,
        tmp_c2(2)   TYPE c,
        tmp_lin1    TYPE i,
        tmp_lin2    TYPE i,
        tmp_lin3(4) TYPE c,
        tmp_i1      TYPE i,
        tmp_i2      TYPE i,
        tmp_n1      TYPE i,
        tmp_n2      TYPE i,
        tmp_o       TYPE i,
        tmp_x       TYPE i,
      END OF temp.

* Data
DATA: tfs(20) TYPE c,
      d_ret   LIKE sy-subrc,
      dcol    TYPE i.

DATA: computer(1)      TYPE c,
      player(1)        TYPE c.

DATA: turn(1)          TYPE c,
      linea            TYPE i,
      offs             TYPE i VALUE 20,
      computer_wins(1) TYPE c,
      player_wins(1)   TYPE c.

* internal tables
DATA: BEGIN OF tab OCCURS 10,
        col TYPE i,
        lin TYPE i,
        x   TYPE i,
        o   TYPE i,
        b   TYPE i,
        xa  TYPE i,
        oa  TYPE i,
        ba  TYPE i,
      END   OF tab.

* Field Symbols
FIELD-SYMBOLS: <fs1>,
               <fs2>,
               <fs3>,
               <fs4>,
               <fs5>,
               <fs6>,
               <fs7>.






**********************************

*Class to handle the FINSHED Event Raised by CL_GUI_TIMER
CLASS my DEFINITION.
  PUBLIC SECTION.
    METHODS : run_handler FOR EVENT finished OF cl_gui_timer.
ENDCLASS.                    "my DEFINITION
DATA timer TYPE REF TO cl_gui_timer.
DATA myh TYPE REF TO my.

*----------------------------------------------------------------------*
*       CLASS my IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS my IMPLEMENTATION.
  METHOD run_handler.
    CALL METHOD timer->run.
    CALL METHOD cl_gui_cfw=>set_new_ok_code
      EXPORTING
        new_code = 'TIMER'.
  ENDMETHOD.                    "run_handler
ENDCLASS.                    "my IMPLEMENTATION

***********************************











* Selection Screen
SELECTION-SCREEN BEGIN OF BLOCK b00
WITH FRAME TITLE text-b00.
PARAMETERS: r_cho1 RADIOBUTTON GROUP radi,
            r_cho2 RADIOBUTTON GROUP radi.
SELECTION-SCREEN END OF BLOCK b00.

*----------------------------------------------------------------------*
* AT SELECTION-SCREEN
*----------------------------------------------------------------------*
AT SELECTION-SCREEN.
  IF r_cho1 = 'X'.
    player   = 'O'.
    computer = 'X'.
  ELSE.
    player   = 'X'.
    computer = 'O'.
  ENDIF.
*----------------------------------------------------------------------*
* AT USER-COMMAND restart game button
*----------------------------------------------------------------------*
AT USER-COMMAND.
  IF syst-ucomm = 'GO'.
    PERFORM start_game.
  ENDIF.

* Warte
  IF sy-ucomm = 'TIMER'.
    PERFORM warte_computer.
  ENDIF.

*----------------------------------------------------------------------*
* START-OF-SELECTION *
*----------------------------------------------------------------------*
START-OF-SELECTION.

* initialisiere Objekte
  CREATE OBJECT timer.
  CREATE OBJECT myh.
  timer->interval = '1'.
  SET HANDLER myh->run_handler FOR ALL INSTANCES.


  PERFORM start_game.

*----------------------------------------------------------------------*
* AT LINE-SELECTION *
*----------------------------------------------------------------------*
AT LINE-SELECTION.
  IF player_wins = ' '
  AND computer_wins = ' '.
    PERFORM decide_turn.
  ENDIF.

* Forms
*---------------------------------------------------------------------*
*       FORM start_game                                               *
*---------------------------------------------------------------------*
FORM start_game.
  SET PF-STATUS '1000'.
  syst-lsind = 1.
  CLEAR: temp.
  CLEAR: c1, c2, c3, c4, c5, c6, c7, c8.
  turn = 'O'.
  CLEAR: tfs, d_ret, dcol, linea.
  PERFORM decide_initial_turn.
ENDFORM.                    "start_game
*---------------------------------------------------------------------*
*       FORM decide_initial_turn                                      *
*---------------------------------------------------------------------*
FORM decide_initial_turn.
  CLEAR player_wins.
  CLEAR computer_wins.
  IF turn = computer.
    PERFORM draw_square.
    turn = player.
  ENDIF.
  PERFORM draw_table.
ENDFORM.                    "decide_initial_turn
*---------------------------------------------------------------------*
*       FORM decide_turn                                              *
*---------------------------------------------------------------------*
FORM decide_turn.
  IF turn = computer.
    PERFORM draw_square.
    turn = player.
    PERFORM draw_table.
    SET PF-STATUS '1000' IMMEDIATELY.
  ELSE.
    PERFORM  verify_selection.
    turn = computer.

    SET PF-STATUS '1000' EXCLUDING 'PICK' IMMEDIATELY.
    CALL METHOD timer->run.
    PERFORM draw_table.
*    PERFORM decide_turn.
  ENDIF.
ENDFORM.                    "decide_turn
*---------------------------------------------------------------------*
*       FORM draw_square                                              *
*---------------------------------------------------------------------*
FORM draw_square.

  PERFORM build_check_table.
  PERFORM extract_square_values.

  DELETE tab WHERE o < temp-tmp_o AND x < temp-tmp_x.

  IF ( temp-tmp_o = 4 AND player = 'O' )
  OR ( temp-tmp_x = 4 AND player = 'X' ).
    player_wins = 'X'.

  ELSEIF temp-tmp_o <> 3 AND temp-tmp_x <> 3.
    DESCRIBE TABLE tab LINES temp-tmp_n1.
    GET TIME.
    temp-tmp_n1 = ( sy-uzeit MOD temp-tmp_n1 ) + 1.
    READ TABLE tab INDEX temp-tmp_n1.

  ELSEIF computer = 'O'.
    PERFORM check_computer_wins_o.

  ELSE.
    PERFORM check_computer_wins_x.
  ENDIF.

  CHECK sy-subrc = 0.
  CHECK player_wins IS INITIAL.

  temp-tmp_col3+0(1) = 'C'.
  temp-tmp_col3+1(1) = tab-col.
  ASSIGN (temp-tmp_col3) TO <fs1>.

  PERFORM fsoffset_change USING tab-lin
                                1
                                computer
                       CHANGING <fs1>.
ENDFORM.                    "draw_square
*---------------------------------------------------------------------*
*       FORM build_check_table                                        *
*---------------------------------------------------------------------*
FORM build_check_table.
  REFRESH tab.
  DO 8 TIMES.
    temp-tmp_col3+0(1) = 'C'.
    temp-tmp_col3+1(1) = sy-index.
    ASSIGN (temp-tmp_col3) TO <fs1>.

    CLEAR tab.
    tab-col = sy-index.
    IF <fs1> CA ' '.
      tab-lin = sy-fdpos.
    ELSE.
      CONTINUE.
    ENDIF.
    PERFORM count_possible CHANGING tab.
    APPEND tab.
  ENDDO.
ENDFORM.                    "build_check_table
*---------------------------------------------------------------------*
*       FORM extract_square_values                                    *
*---------------------------------------------------------------------*
FORM extract_square_values.
  SORT tab BY o DESCENDING
              b DESCENDING
              ba DESCENDING
              oa DESCENDING
              xa x.
  READ TABLE tab INDEX 1.
  temp-tmp_o = tab-o.

  SORT tab BY x DESCENDING
              b DESCENDING
              ba DESCENDING
              xa DESCENDING
              oa o.
  READ TABLE tab INDEX 1.
  temp-tmp_x = tab-x.
ENDFORM.                    "extract_square_values
*---------------------------------------------------------------------*
*       FORM check_computer_wins_o                                    *
*---------------------------------------------------------------------*
FORM check_computer_wins_o.
  IF temp-tmp_o = 3.
    SORT tab BY o DESCENDING
                b DESCENDING
                ba DESCENDING
                oa DESCENDING
                xa x.
    computer_wins = 'X'.
  ELSEIF temp-tmp_x = 3.
    SORT tab BY x DESCENDING
                b DESCENDING
                ba DESCENDING
                xa DESCENDING
                oa o.
  ENDIF.
  READ TABLE tab INDEX 1.
ENDFORM.                    "check_computer_wins_o
*---------------------------------------------------------------------*
*       FORM check_computer_wins_x                                    *
*---------------------------------------------------------------------*
FORM check_computer_wins_x.
  IF temp-tmp_x = 3.
    SORT tab BY x DESCENDING
                b DESCENDING
                ba DESCENDING
                xa DESCENDING
                oa o.
    computer_wins = 'X'.
  ELSEIF temp-tmp_o = 3.
    SORT tab BY o DESCENDING
                b DESCENDING
                ba DESCENDING
                oa DESCENDING
                xa x.
  ENDIF.
  READ TABLE tab INDEX 1.
ENDFORM.                    "check_computer_wins_x
*---------------------------------------------------------------------*
*       FORM count_possible                                           *
*---------------------------------------------------------------------*
FORM count_possible CHANGING ptab STRUCTURE tab.

* Square 1
  temp-tmp_col1 = tab-col - 1.
  temp-tmp_lin1 = tab-lin + 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 2
  temp-tmp_col1 = tab-col.
  temp-tmp_lin1 = tab-lin + 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 3
  temp-tmp_col1 = tab-col + 1.
  temp-tmp_lin1 = tab-lin + 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 4
  temp-tmp_col1 = tab-col - 1.
  temp-tmp_lin1 = tab-lin.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 5
  temp-tmp_col1 = tab-col + 1.
  temp-tmp_lin1 = tab-lin.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 6
  temp-tmp_col1 = tab-col - 1.
  temp-tmp_lin1 = tab-lin - 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 7
  temp-tmp_col1 = tab-col.
  temp-tmp_lin1 = tab-lin - 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.
* Square 8
  temp-tmp_col1 = tab-col + 1.
  temp-tmp_lin1 = tab-lin - 1.
  PERFORM count_squares USING temp-tmp_col1
                              temp-tmp_lin1
                     CHANGING ptab.

* Horizontal
  PERFORM count_linea USING tab-col
                            tab-lin
                            1
                            0
                   CHANGING ptab.
* Vertical
  PERFORM count_linea USING tab-col
                            tab-lin
                            0
                            1
                   CHANGING ptab.
* Diagonal 1
  PERFORM count_linea USING tab-col
                            tab-lin
                            1
                            1
                   CHANGING ptab.
* Diagonal 2
  PERFORM count_linea USING tab-col
                            tab-lin
                            1
                            -1
                   CHANGING ptab.

ENDFORM.                    "count_possible
*---------------------------------------------------------------------*
*       FORM count_squares                                            *
*---------------------------------------------------------------------*
FORM count_squares USING value(pcol) TYPE i
                         value(plin) TYPE i
                CHANGING tab STRUCTURE tab.

  temp-tmp_c1 = 'C '.

  CHECK pcol >= 1
    AND pcol <= 8
    AND plin >= 0
    AND plin <= 7.

  temp-tmp_c1+1(1) = pcol.
  ASSIGN (temp-tmp_c1) TO <fs4>.
  PERFORM fsoffset USING <fs4>
                         plin
                         1
                CHANGING tfs.
  CASE tfs.
    WHEN 'O'.
      ADD 1 TO tab-oa.
    WHEN 'X'.
      ADD 1 TO tab-xa.
    WHEN ' '.
      ADD 1 TO tab-ba.
  ENDCASE.
ENDFORM.                    "count_squares
*---------------------------------------------------------------------*
*       FORM fsoffset                                                 *
*---------------------------------------------------------------------*
FORM fsoffset USING value(p_char)   TYPE c
                    value(p_off)    TYPE i
                    value(p_tam)    TYPE i
           CHANGING value(p_result) TYPE c.

  temp-tmp_ca1(10)    = 'p_char+'.
  temp-tmp_ca1+10(10) = p_off.
  temp-tmp_ca1+20(1)  = '('.
  temp-tmp_ca1+21(10) = p_tam.
  temp-tmp_ca1+31(1)  = ')'.
  CONDENSE temp-tmp_ca1 NO-GAPS.
  ASSIGN (temp-tmp_ca1) TO <fs6>.

  p_result = <fs6>.
ENDFORM.                    "fsoffset
*---------------------------------------------------------------------*
*       FORM count_linea                                              *
*---------------------------------------------------------------------*
FORM count_linea USING value(pcol)
                       value(plin)
                       value(pincc)
                       value(pincl)
              CHANGING tab STRUCTURE tab.

  temp-tmp_c2 = 'C '.

  DO 3 TIMES.
    temp-tmp_i1 = sy-index + 1.
    temp-tmp_cini = pcol - pincc * ( temp-tmp_i1 - 1 ).
    temp-tmp_cfin = pcol.
    temp-tmp_lini = plin - pincl * ( temp-tmp_i1 - 1 ).
    temp-tmp_lfin = plin.

    DO temp-tmp_i1 TIMES.
      IF temp-tmp_cini < 1 OR temp-tmp_cini > 8
      OR temp-tmp_cfin < 1 OR temp-tmp_cfin > 8
      OR temp-tmp_lini > 7 OR temp-tmp_lini < 0
      OR temp-tmp_lfin > 7 OR temp-tmp_lfin < 0.
        temp-tmp_cini = temp-tmp_cini + pincc.
        temp-tmp_cfin = temp-tmp_cfin + pincc.
        temp-tmp_lini = temp-tmp_lini + pincl.
        temp-tmp_lfin = temp-tmp_lfin + pincl.
        CONTINUE.
      ENDIF.

      CLEAR temp-tmp_lin3.

      temp-tmp_c2+1(1) = temp-tmp_cini.
      ASSIGN (temp-tmp_c2) TO <fs5>.
      PERFORM fsoffset USING <fs5>
                             temp-tmp_lini
                             1
                    CHANGING temp-tmp_lin3+0(1).

      temp-tmp_c2+1(1) = temp-tmp_cini + 1 * pincc.
      ASSIGN (temp-tmp_c2) TO <fs5>.
      temp-tmp_n2 = temp-tmp_lini + 1 * pincl.
      PERFORM fsoffset USING <fs5>
                             temp-tmp_n2
                             1
                    CHANGING temp-tmp_lin3+1(1).

      IF temp-tmp_i1 > 2.
        temp-tmp_c2+1(1) = temp-tmp_cini + 2 * pincc.
        ASSIGN (temp-tmp_c2) TO <fs5>.
        temp-tmp_n2 = temp-tmp_lini + 2 * pincl.
        PERFORM fsoffset USING <fs5>
                               temp-tmp_n2
                               1
                      CHANGING temp-tmp_lin3+2(1).
      ENDIF.

      IF temp-tmp_i1 > 3.
        temp-tmp_c2+1(1) = temp-tmp_cini + 3 * pincc.
        ASSIGN (temp-tmp_c2) TO <fs5>.
        temp-tmp_n2 = temp-tmp_lini + 3 * pincl.
        PERFORM fsoffset USING <fs5>
                               temp-tmp_n2
                               1
                      CHANGING temp-tmp_lin3+3(1).
      ENDIF.

      IF temp-tmp_lin3 CO 'O '.
        PERFORM check_line_for_o.
      ELSEIF temp-tmp_lin3 CO 'X '.
        PERFORM check_line_for_x.
      ELSEIF temp-tmp_lin3 CO ' '.
        IF tab-b < temp-tmp_i1.
          tab-b = temp-tmp_i1.
        ENDIF.
      ENDIF.

      temp-tmp_cini = temp-tmp_cini + pincc.
      temp-tmp_cfin = temp-tmp_cfin + pincc.
      temp-tmp_lini = temp-tmp_lini + pincl.
      temp-tmp_lfin = temp-tmp_lfin + pincl.
    ENDDO.
  ENDDO.
ENDFORM.                    "count_linea
*---------------------------------------------------------------------*
*       FORM check_line_for_o                                         *
*---------------------------------------------------------------------*
FORM check_line_for_o.
  IF temp-tmp_lin3 = 'OOOO'.
    temp-tmp_n2 = 4.
  ELSEIF temp-tmp_lin3 CP '*O*O*O*'.
    temp-tmp_n2 = 3.
  ELSEIF temp-tmp_lin3 CP '*O*O*'.
    temp-tmp_n2 = 2.
  ELSEIF temp-tmp_lin3 CP '*O*'.
    temp-tmp_n2 = 1.
  ELSE.
    temp-tmp_n2 = 0.
  ENDIF.

  IF temp-tmp_n2 > tab-o.
    tab-o = temp-tmp_n2.
  ELSEIF temp-tmp_n2 = 0.
    IF tab-b < temp-tmp_i1.
      tab-b = temp-tmp_i1.
    ENDIF.
  ENDIF.
ENDFORM.                    "check_line_for_o
*---------------------------------------------------------------------*
*       FORM check_line_for_x                                         *
*---------------------------------------------------------------------*
FORM check_line_for_x.
  IF temp-tmp_lin3 = 'XXXX'.
    temp-tmp_n2 = 4.
  ELSEIF temp-tmp_lin3 CP '*X*X*X*'.
    temp-tmp_n2 = 3.
  ELSEIF temp-tmp_lin3 CP '*X*X*'.
    temp-tmp_n2 = 2.
  ELSEIF temp-tmp_lin3 CP '*X*'.
    temp-tmp_n2 = 1.
  ELSE.
    temp-tmp_n2 = 0.
  ENDIF.

  IF temp-tmp_n2 > tab-x.
    tab-x = temp-tmp_n2.
  ELSEIF temp-tmp_n2 = 0.
    IF tab-b < temp-tmp_i1.
      tab-b = temp-tmp_i1.
    ENDIF.
  ENDIF.
ENDFORM.                    "check_line_for_x
*---------------------------------------------------------------------*
*       FORM fsoffset_change                                          *
*---------------------------------------------------------------------*
FORM fsoffset_change USING value(p_off)    TYPE i
                           value(p_tam)    TYPE i
                           value(p_valor) TYPE c
                  CHANGING value(p_char)   TYPE c.

  temp-tmp_ca2(10)    = 'p_char+'.
  temp-tmp_ca2+10(10) = p_off.
  temp-tmp_ca2+20(1)  = '('.
  temp-tmp_ca2+21(10) = p_tam.
  temp-tmp_ca2+31(1)  = ')'.
  CONDENSE temp-tmp_ca2 NO-GAPS.
  ASSIGN (temp-tmp_ca2) TO <fs7>.

  <fs7> = p_valor.
ENDFORM.                    "fsoffset_change
*---------------------------------------------------------------------*
*       FORM draw_table                                               *
*---------------------------------------------------------------------*
FORM draw_table.

  PERFORM draw_table_header.

* draw the table
  DO 8 TIMES.
    dcol = 9 - sy-index.
    PERFORM draw_linea USING dcol.
    PERFORM draw_intervals.
  ENDDO.
  PERFORM draw_base_line.

  sy-lsind = sy-lsind - 1.

  PERFORM draw_table_footer.
ENDFORM.                    "draw_table
*---------------------------------------------------------------------*
*       FORM draw_table_header                                        *
*---------------------------------------------------------------------*
FORM draw_table_header.
  ULINE.
  FORMAT COLOR COL_HEADING INTENSIFIED OFF.
  WRITE: /1 syst-vline,
            'CONNECT 4',
         AT syst-linsz syst-vline.
  ULINE.
  FORMAT RESET.
  IF r_cho1 = 'X'.
    WRITE: /3 'Player..:',
              icon_led_green AS ICON.
    WRITE: /3 'Computer:',
              icon_led_red AS ICON.
  ELSE.
    WRITE: /3 'Computer:',
              icon_led_green AS ICON.
    WRITE: /3 'Player..:',
              icon_led_red AS ICON.
  ENDIF.
ENDFORM.                    "draw_table_header
*---------------------------------------------------------------------*
*       FORM draw_table_footer                                        *
*---------------------------------------------------------------------*
FORM draw_table_footer.
  ULINE.
  IF player_wins = 'X'.
    PERFORM player_wins.
  ELSEIF computer_wins = 'X'.
    PERFORM computer_wins.
  ELSE.
    FORMAT COLOR COL_HEADING INTENSIFIED OFF.
    WRITE: /1 syst-vline,
           22 'Click On Column To Drop Playing Piece',
           AT syst-linsz syst-vline.
  ENDIF.
  ULINE.
ENDFORM.                    "draw_table_footer
*---------------------------------------------------------------------*
*       FORM player_wins                                              *
*---------------------------------------------------------------------*
FORM player_wins.
  IF r_cho1 = 'X'.
    FORMAT COLOR COL_POSITIVE INTENSIFIED OFF.
  ELSE.
    FORMAT COLOR COL_NEGATIVE INTENSIFIED OFF.
  ENDIF.
  WRITE: /1 syst-vline,
            'Player Wins!',
         AT syst-linsz syst-vline.
ENDFORM.                    "player_wins
*---------------------------------------------------------------------*
*       FORM computer_wins                                            *
*---------------------------------------------------------------------*
FORM computer_wins.
  IF r_cho2 = 'X'.
    FORMAT COLOR COL_POSITIVE INTENSIFIED OFF.
  ELSE.
    FORMAT COLOR COL_NEGATIVE INTENSIFIED OFF.
  ENDIF.
  WRITE: /1 syst-vline,
            'Computer Wins!',
         AT syst-linsz syst-vline.
ENDFORM.                    "computer_wins
*---------------------------------------------------------------------*
*       FORM draw_base_line                                           *
*---------------------------------------------------------------------*
FORM draw_base_line.
  WRITE: AT /offs sy-uline(41).
ENDFORM.                    "draw_base_line
*---------------------------------------------------------------------*
*       FORM draw_intervals                                           *
*---------------------------------------------------------------------*
FORM draw_intervals.
  WRITE: AT /offs sy-vline.
  DO 8 TIMES.
    WRITE: '  ' HOTSPOT ON, sy-vline.
  ENDDO.
ENDFORM.                    "draw_intervals
*---------------------------------------------------------------------*
*       FORM draw_linea                                               *
*---------------------------------------------------------------------*
FORM draw_linea USING value(p_lin) TYPE i.

  p_lin = p_lin - 1.

  WRITE: AT /offs sy-vline.

  DO 8 TIMES.
    temp-tmp_col4+0(1) = 'C'.
    temp-tmp_col4+1(1) = sy-index.
    ASSIGN (temp-tmp_col4) TO <fs2>.
    PERFORM fsoffset USING <fs2>
                           p_lin
                           1
                  CHANGING tfs.

    IF tfs IS INITIAL.
      WRITE: '  ' HOTSPOT ON.
    ELSE.
      IF tfs = 'O'.
        WRITE icon_led_green AS ICON HOTSPOT OFF.
      ELSE.
        WRITE icon_led_red AS ICON HOTSPOT OFF.
      ENDIF.
    ENDIF.

    WRITE: sy-vline.
  ENDDO.

  linea = 1.
  HIDE: linea.
ENDFORM.                    "draw_linea
*---------------------------------------------------------------------*
*       FORM verify_selection                                         *
*---------------------------------------------------------------------*
FORM verify_selection.

  temp-tmp_lin2 = linea.
  CLEAR linea.

  CHECK sy-ucomm = 'PICK'.
  temp-tmp_col2 = ( sy-cucol - offs + 3 ).
  temp-tmp_i2   = temp-tmp_col2 MOD 5.

  IF temp-tmp_lin2 <> 1
  OR temp-tmp_col2 < 5
  OR temp-tmp_col2 > 43
  OR temp-tmp_i2 > 3.
    MESSAGE e899 WITH 'Invalid Selection'.
  ENDIF.

  temp-tmp_col2 = temp-tmp_col2 DIV 5.

  temp-tmp_ca3(1) = 'C'.
  temp-tmp_ca3+1(1) = temp-tmp_col2.
  ASSIGN (temp-tmp_ca3) TO <fs3>.

  PERFORM fsoffset USING <fs3>
                         7
                         1
                CHANGING tfs.

  IF NOT tfs IS INITIAL.
    MESSAGE e899 WITH 'Invalid Selection'.
  ENDIF.

  IF <fs3> CA ' '.
    PERFORM fsoffset_change USING sy-fdpos
                                  1
                                  player
                         CHANGING <fs3>.
  ELSE.
    PERFORM fsoffset_change USING 0
                                  1
                                  player
                         CHANGING <fs3>.
  ENDIF.

  CLEAR tab.
  tab-col = temp-tmp_col2.

  IF <fs3> CA ' '.
    tab-lin = sy-fdpos - 1.
  ELSE.
    tab-lin = 8.
  ENDIF.

  PERFORM count_possible CHANGING tab.

  IF ( tab-o = 4 AND player = 'O' ) OR
     ( tab-x = 4 AND player = 'X' ).
    player_wins = 'X'.
  ENDIF.

  turn = computer.
ENDFORM.                    "verify_selection


*&---------------------------------------------------------------------*
*&      Form  WARTE_COMPUTER
*&---------------------------------------------------------------------*
*----------------------------------------------------------------------*
FORM warte_computer .
  CALL METHOD timer->cancel.
  PERFORM decide_turn.
ENDFORM.                    " WARTE_COMPUTER